/**
 * Created by WangGuoyan on 2017/2/8.
 */
/**---------------------------------------------------History---------------------------------------------------------*/
/* <p>Title: workflowscript</p>
 * <p>Description: IBatch Workflow Editor Script Doc </p>
 * <p>Copyright: Baosight Software LTD.co Copyright (c) 2002</p>
 * <p>Company: IBatch Software</p>
 * @author 汪国岩
 * @version 1.0
 * <pre>Histroy:
 * 2017-2-8
 *</pre>
 /*--------------------------------------------------------------------------------------------------------------------*/


// JavaScript Document
/*---------------------------------------------------全局变量----------------------------------------------------------*/
var canvas;															//定义画布
var signal;															//绘制连接线信标,加载默认为false,当触发绘制连接线按钮时为true
var started;														//绘制矢量连接线信标
var lines = [];														//存储所有画布上的连接线
var objs = [];														//存储全局元素（线条除外）
var connectors = [];												//存储所有画布上的矢量连接线
var Id = 1;															//连接线和元素识别的id
var processline;													//绘制连接线动态过程线段添删控制名
document.onkeydown = keyDown;										//设置键盘监听
document.onkeyup = keyUp;											//键盘按键抬起事件
document.onmousewheel = mouseWheel;									//注册鼠标滚轮事件
var helppoint;														//连接线提示点
var zoom = 1;														//canvas缩放系数
var txt;															//XML时时存储字符串
var configTxt;														//记录XML字符串存储
var configStore = [];												//时时记录配置
var xmlDoc;															//XML对象
var revocation = false;												//撤销动作新标
var workFlowId = GetUrlParam("workFlowId");							//程序id
var FontSize = 14;													//显示字体大小
var PageName;														//当前页面名称
var ActiveId;														//当前获取待操作的节点id（新建和选中）
var ActiveConnector;												//当前获取等待操作的连接线
var Edit = 1;														//当前处于编辑状态（1 || 0）
var stepAddDivIndex;                                                //选择步骤弹出层

var workFlowEditUrl = serverPath + "RecipePath/addRecipePathResource";		//编辑工作流服务器地址
var workFlowCheckUrl = serverPath + "RecipePath/getRecipePathDetail";			//修改工作流服务器地址
/*---------------------------------------------------------------------------------------------------------------------*/

//初始化编辑器页面
function initPage(opera) {
    try{
        PageName = opera;											//当前页面名称
        signal = false;
        canvas = new fabric.Canvas('canvas');						//选择画布
        canvas.backgroundColor = '#FFF';							//设置画布背景色
        initMouseEvent(opera);										//初始化鼠标事件
        initHelpPoint();											//初始化链接提示点
        clearInstallPage();											//清除属性面板信息
        setEditStateByType("clear");								//隐藏属性面板
        getXMLFromServer();											//读取服务器配置生成当前程序

        if (opera == 'check') {
            fixAllTarget();
        }
        if (opera == 'edit') {
            Start();
            End();
        }
        reLoadTagsCollection();										//刷新节点集合选项
        initCurrentTargetSelector();								//初始化节点集合选择框
    }
    catch(e) {
        alert(e);
    }
}


/*---菜单功能按钮---*/
//“新建”按钮动作
function Create() {
    'use strict';
    var con = confirm('是否放弃目前工作？');
    if (con == true) {
        window.location.href=window.location.href;
        window.location.reload;
    }
    else if (con == false) {
        return;
    }
}

//记录配置按钮
function ConfigInfo() {
    'use strict';
    try{
        configInfo(true);
        configTxt = txt;
    }
    catch(e) {
        alert(e);
    }
}

//加载配置按钮
function LoadConfigInfo() {
    'use strict';
    try{
        canvas.clear();
        ClearPage(function(){
            getXMLFromServer();												//读取服务器配置生成当前程序
        });
    }
    catch(e) {
        alert('配置信息未记录！');
    }
}

//清空工作台
function ClearPage(okCallback) {
    'use strict';
    try{
        canvas.clear();
        connectors = [];
        objs = [];
        clearInstallPage();
        currentTargetClear();
        if(okCallback){
            okCallback();
        }else{
            Start();
            End();
        }
    }
    catch(e) {
        alert(e);
    }
}

//刷新页面
function RefreshPage(){
    'use strict';
    try{
        var newTxt = txt;
        ClearPage(function(){
            loadConfigInfo(newTxt);				//加载
        });
    }
    catch(e){
        alert(e);
    }
}

/*-------------------------------------------------------工具按钮功能块-----------------------------------------------*/
//绘制连接线
function Connect(sig) {
    'use strict';
    //判断是否开始（防止Ctrl和直接点击按钮的冲突）
    if(sig == null){
        started = !started;
    }
    else{
        started = sig;
    }
    setConnectorsSelectable(!started);
    setButtonSelected($('button[onClick="Connect()"]'),started);
    //当前所有节点不可移动或缩放
    for (var i in objs) {
        objs[i].set({
            lockMovementX:started,
            lockMovementY:started,
            lockScalingX:started,
            lockScalingY:started
        });
    }
    if (started == false) {
        hideHelpPoint();
    }
}

//判断某点位于元素的十字线四个点的哪一个点，并返回该点坐标
//Array whitchPointInObject(Array,object)
function whitchPointInObject(Point,Obj) {
    'use strict';
    var distance = 20;
    var left = [];
    var top = [];
    var right = [];
    var bottom = [];
    left = GetPointFromObj(Obj,'L');
    top = GetPointFromObj(Obj,'T');
    right = GetPointFromObj(Obj,'R');
    bottom = GetPointFromObj(Obj,'B');

    if (PointBeside(Point,left,distance)) {
        return(left);
    }
    if (PointBeside(Point,top,distance)) {
        return(top);
    }
    if (PointBeside(Point,right,distance)) {
        return(right);
    }
    if (PointBeside(Point,bottom,distance)) {
        return(bottom);
    }
}

//判断鼠标当前坐标位于元素的十字线四个点的哪一个点，返回点的位置名称
//Str whitchPointInObjectStr(Array, object)
function whitchPointInObjectStr(Point,Obj) {
    'use strict';
    var distance = 20;
    var left = [];
    var top = [];
    var right = [];
    var bottom = [];
    left = GetPointFromObj(Obj,'L');
    top = GetPointFromObj(Obj,'T');
    right = GetPointFromObj(Obj,'R');
    bottom = GetPointFromObj(Obj,'B');

    if (PointBeside(Point,left,distance)) {
        return('L');
    }
    if (PointBeside(Point,top,distance)) {
        return('T');
    }
    if (PointBeside(Point,right,distance)) {
        return('R');
    }
    if (PointBeside(Point,bottom,distance)) {
        return('B');
    }
}

//判断A点是否在B指定范围内
//Boolean PointBeside(array,array,num-范围距离)
function PointBeside(PointA, PointB, distance) {
    'use strict';
    var Bx1 = PointB[0] - distance;
    var Bx2 = PointB[0] + distance;
    var By1 = PointB[1] - distance;
    var By2 = PointB[1] + distance;
    if (PointA[0] > Bx1 && PointA[0] < Bx2 && PointA[1] > By1 && PointA[1] < By2) {
        return (true);
    }
    else {
        return (false);
    }
}

////向量箭头连接线设置
//function VectorConnect(x1,y1,x2,y2){
//	'use strict'
//	var Vectors = [];
//	Vectors[0] = new fabric.Line([x1,y1,x2,y2], {
//		stroke: 'black',
//      	strokeWidth: 1,
//      	selectable: true
//	});
//	var h = Math.sqrt(27);
//
//	//根据两点所在位置获得箭头部位旋转角度
//	var ang;									//角度值
//	var Dvalue = Math.abs(x2 - x1);				//横坐标差值
//	var distance = Distance(x1,y1,x2,y2);		//线段距离
//	var division = ((Dvalue * 10000) / (distance * 10000));
//	var pi = ((180 * 10000) / (Math.PI * 10000));
//	//相对于终点，起点在第一象限
//	if(x2 >= x1 && y2 >= y1){
//		ang = Math.acos(division) * pi + 90;
//	}
//	//起点在第二象限
//	if(x2 < x1 && y2 >= y1){
//		ang = Math.asin(division) * pi + 180;
//	}
//	//起点在第三象限
//	if(x2 < x1 && y2 < y1){
//		ang = Math.acos(division) * pi + 270;
//	}
//	//起点在第四象限
//	if(x2 >= x1 && y2 < y1){
//		ang = Math.asin(division) * pi;
//	}
//
//	Vectors[1] = new fabric.Triangle({
//		height:h,
//		width:6,
//		fill:'black',
//		angle:ang,
//		originX:'center'
//	});
//	var po = new fabric.Point(x2,y2);
//	Vectors[1].setPositionByOrigin(po, 'center', 'top');
//	var V = new fabric.Group(Vectors,{
//		lockScalingFlip:true,
//		lockScalingY:true,
//		lockScalingX:true,
//		hasRotatingPoint:false,
//		lockUniScaling:true,
//		selectable: false,
//		hasControls:false,
//		evented:false
//	});
//	canvas.add(V);
//	canvas.sendToBack(V);
//	vectors.push(V);
//}


//判断指定点是否在指定Object内
//Boolearn PointInObject(number,number,obj)
function PointInObject(x,y,target) {
    'use strict'
    var leftSide = target.get('left');
    var topSide = target.get('top');
    var rightSide = target.get('left') + target.getWidth();
    var bottomSide = target.get('top') + target.getHeight();
    if ( x >= leftSide && x <= rightSide && y >= topSide && y <= bottomSide) {
        return true;
    }
    else {
        return false;
    }
}

//获取Object的border指定关键点（线条类除外）
//参数说明：L:left, B:bottom, R:right, T:Top, LT:left&top, LB:left&bottom, RB:right&bottom, RT:right&top, C:Center
//Array(x,y) GetPointFromObj(obj,string)
function GetPointFromObj(target,point) {
    'use strict';
    var co = [];
    co[0] = target.get('left');
    co[1] = co[0] + (target.getWidth() / 2);
    co[2] = co[0] + target.getWidth();
    co[3] = target.get('top');
    co[4] = co[3] + (target.getHeight() / 2);
    co[5] = co[3] + target.getHeight();
    if (point == 'L') {
        return([co[0],co[4]]);
    }
    else if (point == 'B') {
        return([co[1],co[5]]);
    }
    else if (point == 'R') {
        return([co[2],co[4]]);
    }
    else if (point == 'T') {
        return([co[1],co[3]]);
    }
    else if (point == 'LT') {
        return([co[0],co[3]]);
    }
    else if (point == 'LB') {
        return([co[0],co[5]]);
    }
    else if (point == 'RB') {
        return([co[2],co[5]]);
    }
    else if (point == 'RT') {
        return([co[2],co[3]]);
    }
    else if (point == 'C') {
        return([co[1],co[4]]);
    }
}





/*------------------------------------------------------节点、连接线绘制功能块-------------------------------------------*/
//绘制矩形按钮
function Rectangle() {
    'use strict';
    ActiveId = null;
    showStepSelect();			//弹出步骤选择
}

//绘制矩形节点
function drawRectangleCmd() {
    'use strict';
    var Task = [];
    //底层矩形样式
    Task[0] = new fabric.Rect({
        left:50,
        top:50,
        height:80,
        width:160,
        stroke:'#0000CC',
        strokeWidth:0.5,
        fill:'#3868A3'
    });
    //梯形高光效果
    Task[1] = new fabric.Path('M 51 50 L 209 50 L 205 55 L 55 55 z',{
        stroke:'#4485D5'
    });
    Task[1].setGradient('fill',{
        type:'linear',
        x1:100,
        y1:0,
        x2:100,
        y2:4,
        colorStops:{
            0:'#366DB1',
            0.5:'#FFFFFF',
            1:'#4485D5',
        }
    });
    //第二层矩形样式
    Task[2] = new fabric.Rect({
        left:55,
        top:55,
        height:70,
        width:150,
    });
    Task[2].setGradient('fill',{
        type:'linear',
        x1:100,
        y1:0,
        x2:100,
        y2:80,
        colorStops:{
            0:'#4485D5',
            1:'#366DB1'
        }
    });

    Task[3] = new fabric.Text('',{
        left:65,
        top:65,
        fontSize: 12,
        fontFamily: '宋体',
        textAlign:'center'
    });
    var task = new fabric.Group(Task);
    task.set({
        hasBorders:false,							//不显示控制器边框
        hasControls:false,							//不显示控制器
        lockScalingFlip:true,						//禁止翻转
        id:Id,
        objType:'Task'
    });
    ActiveId = task.id;
    task.setControlVisible('mtr',false);			//隐藏旋转控制器
    canvas.add(task);
    objs.push(task);
    canvas.renderAll();
    Id += 1;
    configOnTime();									//记录配置
    reLoadTagsCollection();
}

//绘制开始标记
function Start() {
    'use strict';
    if(checkUpTargetByType('Start')){
        return;
    }else{
        var StartTag = [];
        StartTag[0] = new fabric.Rect({
            left:50,
            top:50,
            width:150,
            height:50,
            rx:25,
            ry:25,
        });
        StartTag[0].setGradient('fill', {
            type:'linear',
            x1:100,
            y1:0,
            x2:100,
            y2:15,
            colorStops:{
                0:'#e5ff88',
                1:'#7b9942'
            }
        });

        //上层图形
        StartTag[1] = new fabric.Rect({
            left:55,
            top:55,
            height:40,
            width:140,
            rx:20,
            ry:20
        });
        StartTag[1].setGradient('fill',{
            type:'linear',
            x1:100,
            y1:0,
            x2:100,
            y2:40,
            colorStops:{
                0:'#a5cd4e',
                1:'#8aac40'
            }
        });

        StartTag[2] = new fabric.Text('开始', {
            left:65,
            top:72,
            fontSize: FontSize,
            fontFamily: '宋体',
            textAlign:'center'
        });

        var startTag = new fabric.Group(StartTag);
        startTag.set({
            hasBorders:false,							//不显示控制器边框
            hasControls:false,							//不显示控制器
            lockScalingFlip: true,
            id:0,
            objType: 'Start',
            stepname:"开始"
        });
        startTag.setControlVisible('mtr',false);
        canvas.add(startTag);
        objs.push(startTag);
        centerTextForTarget(startTag);				//文字居中对齐
        configOnTime();			//记录配置
    }
}


//绘制结束标记
function End() {
    if(checkUpTargetByType('End')){
        return
    }else{
        var EndTag = [];
        EndTag[0] = new fabric.Rect({
            left:50,
            top:50,
            width:150,
            height:50,
            rx:25,
            ry:25,
        });
        EndTag[0].setGradient('fill', {
            type:'linear',
            x1:100,
            y1:0,
            x2:100,
            y2:15,
            colorStops:{
                0:'#e5ff88',
                1:'#7b9942'
            }
        });

        //上层图形
        EndTag[1] = new fabric.Rect({
            left:55,
            top:55,
            height:40,
            width:140,
            rx:20,
            ry:20
        });
        EndTag[1].setGradient('fill',{
            type:'linear',
            x1:100,
            y1:0,
            x2:100,
            y2:40,
            colorStops:{
                0:'#a5cd4e',
                1:'#8aac40'
            }
        });
        EndTag[2] = new fabric.Text('结束', {
            left:65,
            top:72,
            fontSize: FontSize,
            fontFamily: '宋体',
            textAlign:'center'
        });

        var circle = new fabric.Group(EndTag);
        circle.set({
            hasBorders:false,							//不显示控制器边框
            hasControls:false,							//不显示控制器
            lockScalingFlip:true,
            id:99999999,
            objType:'End',
            stepname:"结束"
        });
        circle.setControlVisible('mtr', false);
        canvas.add(circle);
        objs.push(circle);
        centerTextForTarget(circle);					//文字居中对齐
        configOnTime();				//记录配置
    }
}

//绘制菱形按钮
function Diamond(){
    'use strict';
    drawDiamondCmd();			//绘制菱形
}

//绘制菱形方法
function drawDiamondCmd(){
    'use strict';
    var rects = [];
    //底层菱形
    rects[0] = new fabric.Rect({
        left:50,
        top:50,
        width:90,
        height:90,
        angle:45
    });
    var dis = getDistance(50, 50, 140, 140) / 2;
    //上层菱形
    rects[1] = new fabric.Rect({
        left:50,
        top:50,
        width:75,
        height:75,
        angle:45,
        fill:'red'
    });
    var po = new fabric.Point(50, 50 + dis);
    //两层菱形位置及样式渲染
    rects[1].setPositionByOrigin(po, 'center', 'center');
    rects[0].setGradient('fill', {
        type:'linear',
        x1:30,
        y1:30,
        x2:60,
        y2:60,
        colorStops:{
            0:'#db4b48',
            1:'#a23533'
        }
    });
    rects[1].setGradient('fill', {
        type:'linear',
        x1:30,
        y1:30,
        x2:60,
        y2:60,
        colorStops:{
            0:'#d64440',
            1:'#b13834'
        }
    });
    rects[2] = new fabric.Text('', {
        left:25,
        top:90,
        fontSize: 12,
        fontFamily: '宋体',
        textAlign:'center'
    });
    var Gate = new fabric.Group(rects);
    Gate.set({
        hasBorders:false,							//不显示控制器边框
        hasControls:false,							//不显示控制器
        lockScalingFlip:true,
        id:Id,
        objType:'Gate'
    });
    ActiveId = Gate.id;
    Gate.setScaleY(0.7);
    Gate.setControlVisible('mtr', false);
    canvas.add(Gate);
    objs.push(Gate);
    Id += 1;
    configOnTime();                      	//记录配置
    reLoadTagsCollection();
}
/*---------------------------------------------------------------------------------------------------------------------*/





//将元素发送到最顶端
function Shift(){
    'use strict';
    var activeObject = canvas.getActiveObject();
    if (activeObject)
    {
        canvas.bringToFront(activeObject);
    }
}

//删除元素按钮
function Delete(){
    'use strict';
    var activeObject = canvas.getActiveObject() || ActiveConnector;								//选取当前活动的object
    var numbers = [];																			//待删除的连接线序数
    if (activeObject.objType != "Start" || "End") {
        canvas.remove(activeObject);
        //判断为节点元素
        if (activeObject.objType == "Gate" || "Task") {
            for (var i in connectors) {
                if (connectors[i].endId == activeObject.id || connectors[i].headId == activeObject.id) {
                    numbers.push(i);															//取出与该节点相连的连接线序数
                    canvas.remove(connectors[i]);												//删除与该节点相连的连接线
                }
            }
            for (var i = numbers.length - 1; i >= 0; i--) {
                connectors.splice(numbers[i],1);												//在connectors删除与该节点有关的项
            }
            for (var i in objs) {
                if (objs[i].id == activeObject.id) {
                    objs.splice(i,1);															//在objs中删除对应的项
                }
            }
        }
        //判断为连接线元素
        if (activeObject.objType == "Connector") {
            for(var i in connectors){
                if(	connectors[i] == activeObject){
                    connectors.splice(i,1);
                }
            }
        }
        reLoadTagsCollection();																	//刷新节点集合
    }
}

//生成两个节点之间最短路径连接方案
function getOptimalConnection(starttarget, endtarget){
    'use strict';
    var startpo;
    var endpo;
    var center1 = new KeyPoint(GetPointFromObj(starttarget, 'C')[0], GetPointFromObj(starttarget, 'C')[1], '');		//起始节点中点
    var center2 = new KeyPoint(GetPointFromObj(endtarget, 'C')[0], GetPointFromObj(endtarget, 'C')[1], '');			//尾节点中点
    if (Math.abs(center2.y - center1.y) > Math.abs(center2.x - center1.x)){
        if(center2.y > center1.y){
            startpo = new KeyPoint(GetPointFromObj(starttarget, 'B')[0], GetPointFromObj(starttarget, 'B')[1], 'B');
        }
        if(center2.y < center1.y){
            startpo = new KeyPoint(GetPointFromObj(starttarget, 'T')[0], GetPointFromObj(starttarget, 'T')[1], 'T');
        }
    }
    if (Math.abs(center2.x - center1.x) > Math.abs(center2.y - center1.y)){
        if(center2.x < center1.x){
            startpo = new KeyPoint(GetPointFromObj(starttarget, 'L')[0], GetPointFromObj(starttarget, 'L')[1], 'L');
        }
        if(center2.x > center1.x){
            startpo = new KeyPoint(GetPointFromObj(starttarget, 'R')[0], GetPointFromObj(starttarget, 'R')[1], 'R');
        }
    }
    endpo = getOptimalPoint(startpo, endtarget);
    return([startpo, endpo]);
}

//获取一个点与一个节点中最近的连接点
function getOptimalPoint(po, target){
    'use strict';
    var pos = [];
    pos = getConsFromTarget(target);				//取出节点的四个连接点
    var result = compareDistance(pos[0], pos[1], pos[2], pos[3], po);
    return(result);
}

//获取一个节点的四个连接点
//Array(left, top, right, bottom)
function getConsFromTarget(target){
    'use strict';
    var leftcon = new KeyPoint(GetPointFromObj(target, 'L')[0], GetPointFromObj(target, 'L')[1], 'L');
    var topcon = new KeyPoint(GetPointFromObj(target, 'T')[0], GetPointFromObj(target, 'T')[1], 'T');
    var rightcon = new KeyPoint(GetPointFromObj(target, 'R')[0], GetPointFromObj(target, 'R')[1], 'R');
    var bottomcon = new KeyPoint(GetPointFromObj(target, 'B')[0], GetPointFromObj(target, 'B')[1], 'B');
    return([leftcon, topcon, rightcon, bottomcon]);
}

//比较四个点到定点之间的距离,返回最小值点坐标
function compareDistance(po1, po2, po3, po4, potag) {
    'use strict';
    var d1 = getDistance(po1, potag);
    var d2 = getDistance(po2, potag);
    var d3 = getDistance(po3, potag);
    var d4 = getDistance(po4, potag);
    var mi = Math.min(d1, d2, d3, d4);
    if (mi == d1) {
        return(po1);
    }
    else if (mi == d2) {
        return(po2);
    }
    else if (mi == d3) {
        return(po3);
    }
    else if (mi == d4) {
        return(po4);
    }
}

//计算两点之间的距离
function getDistance(po1, po2) {
    'use strict';
    var a1 = Math.pow(Math.abs(po1.x - po2.x), 2);
    var a2 = Math.pow(Math.abs(po1.y - po2.y), 2);
    var a3 = a1 + a2;
    return(Math.sqrt(a3));
}

//定义鼠标事件集
function initMouseEvent(operate) {
    'use strict';
    var StartPoint;					//起点坐标点
    var EndPoint;					//终点坐标点
    var ProcessPoint;				//链接过程提示点
    var process = false;			//连接线过程信标
    var ending = false;				//结束连接线绘制信标
    var starttarget;				//起始节点元素

    //鼠标按下时
    canvas.on('mouse:down', function(o) {
        /*手动绘制连接线起点部分*/
        if (started) {
            //取得当前活动元素
            var target = canvas.getActiveObject();
            starttarget = target;
            if (target) {
                /*鼠标当前坐标*/
                var p = canvas.getPointer(o.e);
                var po = [];
                po[0] = p.x;
                po[1] = p.y;
                var position = whitchPointInObjectStr(po,target);
                var point = [];
                point = whitchPointInObject(po,target);
                if (point) {
                    //将当前点击的元素指定起始点坐标作为起点对象存入
                    StartPoint = new KeyPoint(point[0], point[1], position);
                    started = false;				//结束起点过程
                    process = true;					//开始过程连接线绘制
                    ending = true;					//开始连接线终点过程
                    //定义过程提示线终点，绘制过程提示线
                    var p = new KeyPoint(point[0] + 1, point[1] + 1, '');
                    drawProcessLine(StartPoint, StartPoint);
                }
                /*鼠标获取到可选元素但没有在连接点上*/
                else {
                    return;
                }
            }
            /*鼠标点击没有在可选元素内，结束本次绘制*/
            else {
                return;
            }
        }
    });

    //鼠标移动
    canvas.on('mouse:move',function(o) {
        /*绘制连接线过程（动态线提示）*/
        if (process) {
            var p = canvas.getPointer(o.e);
            ProcessPoint = new KeyPoint(p.x, p.y, 'process');
            processline.set({
                x1:StartPoint.x,
                y1:StartPoint.y,
                x2:ProcessPoint.x,
                y2:ProcessPoint.y
            });
            canvas.renderAll();
        }

        /*提示连接点*/
        if (started == true || process == true) {
            var p = canvas.getPointer(o.e);
            showConnectHelpPoint(p);
        }
    });

    //鼠标抬起
    canvas.on('mouse:up',function(o) {
        /*手动绘制连接线终点部分*/
        if(ending){
            var id;
            var p = canvas.getPointer(o.e);
            var target = canvas.getActiveObject();
            var po = [];
            po[0] = p.x;
            po[1] = p.y;
            //遍历到当前鼠标坐标下的元素，获取指定点位置，存入终点对象
            for (var i in objs) {
                //如果鼠标当前下有可选元素
                if (PointInObject(p.x, p.y, objs[i])) {
                    if (objs[i] == starttarget) {
                        StartPoint = EndPoint = null;
                        canvas.remove(processline);
                        return;
                    }
                    id = objs[i].id;
                    var position = whitchPointInObjectStr(po, objs[i]);
                    var point = [];
                    point = whitchPointInObject(po, objs[i]);
                    //结束时取到终点坐标
                    if (point) {
                        EndPoint = new KeyPoint(point[0],point[1],position);
                        hideHelpPoint();													//隐藏连接提示点
                        process = false;
                        ending = false;
                        started = true;
                    }
                    //在元素内，但没有对应到点
                    else {
                        StartPoint = EndPoint = null;
                        process = ending = false;
                        canvas.remove(processline);
                        hideHelpPoint();													//隐藏连接提示点
                        started = true;
                        return;
                    }
                }
            }
            //鼠标抬起时获取到终点坐标
            if (EndPoint) {
                var keypoints = [];
                keypoints = getKeyPoints(StartPoint,EndPoint);
                var connector = strokeConnector(keypoints);
                connector.set({
                    startPo:StartPoint.position,									//连接线起点坐标相对元素位置
                    endPo:EndPoint.position,										//连接线终点坐标相对元素位置
                    headId:target.id,												//连接线起点连接元素id
                    endId:id														//连接线终点连接元素id
                });
                canvas.add(connector);												//绘制连接线
                connectors.push(connector);											//储存连接线
                canvas.sendToBack(connector);										//将连接线放在canvas堆栈最底层
                setConnectorsSelectable(false);										//连接线不可选(fabric选中效果过滤)
                EndPoint = StartPoint = null;
                canvas.remove(processline);											//移除动态连接线
                hideHelpPoint();													//隐藏提示点
                process = ending = false;
                started = true;
                reLoadTagsCollection();												//刷新节点集合
            }
            //鼠标抬起时没有获取到终点坐标
            else {
                canvas.remove(processline);
                StartPoint = EndPoint = null;
                hideHelpPoint();
                process = ending = false;
                started = true;
                return;
            }
        }
    });

    //拖动元素
    canvas.on('object:moving', function(e) {
        var p = e.target;
        var po = [];
        var e = event || window.event;
        var x = e.clientX + 10;
        var y = e.clientY - 40;

        //刷新节点以及连接线
        arrangeTarget(p);
        canvas.renderAll();
        reDrawConnector(p);
        freshCanvas();
    });

    //缩放元素
    canvas.on('object:scaling',function(e) {
        var p = e.target;
        reDrawConnector(p);
    });

    //元素被选中
    canvas.on('object:selected',function(e) {
        var p = e.target;
        var po = [];
        var e = event || window.event;
        var x = e.clientX + 10;
        var y = e.clientY - 40;

        //清除属性面板
        clearInstallPage();

        //清除选择状态
        selectCleared();

        //显示属性信息
        showInfo(p);

        //节点集合中显示当前节点
        showCurrentTatgetSelect(p);

        //设置连接线选中状态(样式)
        if (p.objType == "Connector") {
            setConnectorSelected(p);
        }

        //选中判断项或步骤时将全局ActiveId替换为当前id
        if (p.objType == "Gate" || "Task") {
            setObjectSelected(p);
            ActiveId = p.id;
        }
    });

    //清除选择状态
    canvas.on('selection:cleared', function(e) {
        clearInstallPage();									//清除属性面板信息
        setEditStateByType("clear");						//隐藏属性面板
        selectCleared();									//清除选中状态
    });

    //元素属性改变
    canvas.on('object:modified', function(e) {
        configOnTime();
    });
}

//通过鼠标滚轮缩放canvas
function mouseWheel(e)
{
    var point = new fabric.Point(0,0);
    var wheel = e.wheelDelta/120;
    //Alt键辅助
    if (e.altKey) {
        e.preventDefault();
        //滚轮向上滑动
        if (wheel>0) {
            if (zoom >= 1.6) return;
            zoom += 0.1;
            canvas.zoomToPoint(point,zoom);
            showZoomData();
        }
        //向下滑动
        else {
            if (zoom <= 0.4) {
                return;
            }
            zoom -= 0.1;
            canvas.zoomToPoint(point,zoom);
            showZoomData();
        }
    }
    else{
        return;
    }
}

//键盘按下事件
function keyDown(e) {
    var code = e.which;
    //alert(code);
    try{
        if (PageName == 'edit' && Edit == 1){
            switch(code)
            {
                case 17: e.preventDefault(); Connect(true); break;				//Ctrl辅助绘制连接线
                case 37: e.preventDefault(); moveTarget('left'); break;			//方向左
                case 38: e.preventDefault(); moveTarget('up'); break;			//方向上
                case 39: e.preventDefault(); moveTarget('right'); break;		//方向右
                case 40: e.preventDefault(); moveTarget('down'); break;			//方向下
                case 46: Delete(); break;										//Delete键删除元素
                case 82: RefreshPage(); break;									//R建刷新
                case 90: if (e.ctrlKey) {
                    revocationInfo();
                }; break;											//Ctrl + Z撤销
            }
        }

    }
    catch(e){
        alert(e);
    }
}

//键盘抬起事件
function keyUp(e) {
    if (PageName == 'edit') {
        Connect(false);
    }
}

//移动节点（键盘控制）
function moveTarget(direction) {
    'use strict';
    var target = canvas.getActiveObject();						//获取当前活动节点
    var x = GetPointFromObj(target, 'LT')[0];					//取其当前左上角原点坐标
    var y = GetPointFromObj(target, 'LT')[1];
    if (direction == 'left') {											//判断方向
        if (x <= 0) return;												//越界中断
        else{
            var point = new fabric.Point(x - 10,y);				//定义新位置标定点
            target.setPositionByOrigin(point,'left','top');		//移动
            arrangeTarget(target);										//贴附到指定网格
            canvas.renderAll();
            reDrawConnector(target);
            freshCanvas();
        }
    }
    else if (direction == 'up') {
        if (y <= 0) return;
        else {
            var point = new fabric.Point(x, y - 10);
            target.setPositionByOrigin(point, 'left', 'top');
            arrangeTarget(target);
            canvas.renderAll();
            reDrawConnector(target);
            freshCanvas();
        }
    }
    else if (direction == 'right') {
        if (x >= 2900) return;
        else {
            var point = new fabric.Point(x + 10, y);
            target.setPositionByOrigin(point, 'left', 'top');
            arrangeTarget(target);
            canvas.renderAll();
            reDrawConnector(target);
            freshCanvas();
        }
    }
    else if(direction == 'down') {
        if (y >= 2900) return;
        else {
            var point = new fabric.Point(x, y + 10);
            target.setPositionByOrigin(point, 'left', 'top');
            arrangeTarget(target);
            canvas.renderAll();
            reDrawConnector(target);
            freshCanvas();
        }
    }
}






/*-------------------------------------------------------连接线绘制、设置功能块-----------------------------------------*/
//绘制动态引导线
function drawProcessLine(startpoint,endpoint) {
    'use strict';
    processline = new fabric.Line([startpoint.x, startpoint.y, endpoint.x, endpoint.y], {
        stroke:'#999',
        strokeWidth:1.5,
        type:'process',
        opacity:0.5
    });
    canvas.add(processline);
}

//（跳板）获取元素中的指定点，返回对象
function getOPointFromObj(target, str){
    'use strict';
    var po = [];
    po = GetPointFromObj(target, str);
    return(new fabric.Point(po[0], po[1]));
}

//所有连接线可选状态
function setConnectorsSelectable(sig){
    'use strict';
    if (sig == false) {
        for (var i in connectors) {
            connectors[i].set({
                selectable:false
            });
        }
    }
    else if (sig == true) {
        for (var i in connectors) {
            connectors[i].set({
                selectable:true
            });
        }
    }
}

//绘制连接线方法
//method strokeConnector(array)
function strokeConnector(keypoints) {
    'use strict';
    var connectorlines = [];
    for (var i = 0; i < keypoints.length-1; i++) {
        connectorlines[i] = new fabric.Line([keypoints[i].x, keypoints[i].y, keypoints[i+1].x, keypoints[i+1].y],{
            stroke: 'black',
            strokeWidth: 1,
            lockMovementX:true,
            lockMovementY:true,
            lockScalingX:true,
            lockScalingY:true,
            lockRotation:true,
            strokeLineCap: 'round'
        });
    }
    var cap = makeVCap(keypoints[keypoints.length - 1]);
    connectorlines.push(cap);
    var connector = new fabric.Group(connectorlines);
    connector.set({
        hasBorders:false,
        hasControls:false,
        objType:'Connector',
        CoType:'结束-开始'
    });
    setConnectorClear(connector);
    return(connector);
}

//定义连接关键点
var KeyPoint = function(x, y, position) {
    'use strict';
    //关键点的坐标
    this.x = x;
    this.y = y;
    //关键点位置描述(str)
    this.position = position;
}

//计算两点的中点
//Obj getCenterPoint(obj,obj)
function getCenterPoint(point1,point2) {
    'use strict';
    var x;
    var y;
    var dx = Math.abs(point1.x - point2.x) / 2;
    var dy = Math.abs(point1.y - point2.y) / 2;
    x = Math.min(point1.x,point2.x) + dx;
    y = Math.min(point1.y,point2.y) + dy;
    return new KeyPoint(x,y,'');
}

//绘制连接线箭头
//method makeVCap(obj)
function makeVCap(point) {
    'use strict';
    var ang;
    //根据终点于元素位置设置箭头角度
    if (point.position == "L") {
        ang = 90;
    }
    if (point.position == "T") {
        ang = 180;
    }
    if (point.position == "R") {
        ang = 270;
    }
    if (point.position == "B") {
        ang = 0;
    }
    //定义箭头
    var vcap = new fabric.Triangle({
        height:7,
        width:10,
        fill:'black',
        angle:ang,
        originX:'center'
    });
    var po = new fabric.Point(point.x, point.y);
    vcap.setPositionByOrigin(po, 'center', 'top');
    return(vcap);
}


//根据获得起终点获得关键点
//array getKeyPoints(obj,obj)
function getKeyPoints(startpoint,endpoint){
    'use strict';
    var d = 10;								//起始点和元素的距离
    var keypoints = [];						//连接点集合
    keypoints[0] = startpoint;

    /*****起点在元素上方*****/
    if (startpoint.position == 'T') {
        var vs = new KeyPoint(startpoint.x,startpoint.y - d,'key');		//起点向量点
        keypoints[1] = vs;
        //终点在元素上方
        if (endpoint.position == 'T') {
            var ve = new KeyPoint(endpoint.x,endpoint.y - d,'key');		//终点向量点
            //终点在起点上方
            if (endpoint.y < startpoint.y) {
                keypoints[2] = new KeyPoint(keypoints[1].x, endpoint.y - d, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点下方
            else if (endpoint.y > startpoint.y) {
                keypoints[2] = new KeyPoint(endpoint.x, keypoints[0].y - d, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }

        }
        //终点在元素右方
        if (endpoint.position == 'R') {
            var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
            //终点在起点上方
            if (endpoint.y < startpoint.y) {
                //终点在起点左边
                if (endpoint.x < startpoint.x) {
                    keypoints[2] = new KeyPoint(keypoints[0].x, endpoint.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
                //终点在起点右边
                if (endpoint.x > startpoint.x) {
                    var cy = getCenterPoint(vs,ve).y;
                    keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                    keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                //终点和起点同一水平
                if (endpoint.x == startpoint.x) {
                    keypoints[2] = ve;
                    keypoints[3] = endpoint;
                    return(keypoints);
                }
            }
            //终点在起点下方
            else if (endpoint.y > startpoint.y) {
                //终点在起点右边
                if (endpoint.x > startpoint.x) {
                    keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
                //终点在起点左边
                if (endpoint.x < startpoint.x) {
                    var cx = getCenterPoint(vs,ve).x;
                    keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                    keypoints[3] = new KeyPoint(cx, ve.y, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                //终点和起点垂直相同
                if (endpoint.x = startpoint.x) {
                    keypoints[2] = ve;
                    keypoints[3] = endpoint;
                    return(keypoints);
                }
            } else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素下方
        else if (endpoint.position == 'B') {
            var ve = new KeyPoint(endpoint.x, endpoint.y + d);
            //终点在起点上方
            if (endpoint.y < startpoint.y) {
                var cy = getCenterPoint(startpoint,endpoint).y;
                keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            //终点在起点下面
            else if (endpoint.y > startpoint.y) {
                var cx = getCenterPoint(vs,ve).x;
                keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                keypoints[3] = new KeyPoint(cx, ve.y, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            else{
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素左边
        else if (endpoint.position == 'L') {
            var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
            //终点在起点上边
            if (endpoint.y < startpoint.y) {
                //终点在起点左边
                if (endpoint.x < startpoint.x) {
                    var cy = getCenterPoint(vs,ve).y;
                    keypoints[2] = new KeyPoint(startpoint.x, cy, 'key');
                    keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                //终点在起点右边
                else if (endpoint.x > startpoint.x) {
                    keypoints[2] = new KeyPoint(startpoint.x, endpoint.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
                //终点和起点在同一垂直线上
                else{
                    keypoints[2] = ve;
                    keypoints[3] = endpoint;
                    return(keypoints);
                }
            }
            //终点在起点下边
            if (endpoint.y > startpoint.y) {
                //终点在起点左边
                if (endpoint.x < startpoint.x) {
                    keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
                //终点在起点右边
                else if (endpoint.x > startpoint.x) {
                    var cx = getCenterPoint(vs,ve).x;
                    keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                    keypoints[3] = new KeyPoint(cx, endpoint.y, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                else{
                    keypoints[2] = ve;
                    keypoints[3] = endpoint;
                    return(keypoints);
                }
            }
        }
    }

    /*****起点在元素右边*****/
    if (startpoint.position == "R") {
        var vs = new KeyPoint(startpoint.x + d, startpoint.y, 'key');
        keypoints[1] = vs;
        //终点在元素上边
        if (endpoint.position == "T") {
            var ve = new KeyPoint(endpoint.x, endpoint.y - d, 'key');
            //终点在起点上方
            if (endpoint.y < startpoint.y) {
                keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点下方
            else if (endpoint.y > startpoint.y) {
                //终点在起点左边
                if (endpoint.x < startpoint.x) {
                    var cy = getCenterPoint(vs,ve).y;
                    keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                    keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                //终点在起点右边
                if(endpoint.x > startpoint.x){
                    keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
            }
            else{
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素右边
        if(endpoint.position == "R"){
            var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
            //终点在起点右边
            if(endpoint.x > startpoint.x){
                keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点左边
            else if(endpoint.x < startpoint.x){
                keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            else{
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素下边
        if(endpoint.position == "B"){
            var ve = new KeyPoint(endpoint.x, endpoint.y + d, 'key');
            //终点在起点下方
            if(endpoint.y > startpoint.y){
                keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点上方
            else if(endpoint.y < startpoint.y){
                //终点在起点左边
                if(endpoint.x < startpoint.x){
                    var cy = getCenterPoint(vs, endpoint).y;
                    keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                    keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                //终点在起点右边
                if(endpoint.x > startpoint.x){
                    keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
            }
            else{
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素左边
        if(endpoint.position == "L"){
            var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
            //终点在起点左边
            if(endpoint.x < startpoint.x){
                var cy = getCenterPoint(vs,ve).y;
                keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            //终点在起点右边
            else if(endpoint.x > startpoint.x){
                var cx = getCenterPoint(vs,ve).x;
                keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                keypoints[3] = new KeyPoint(cx, ve.y, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            else{
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
    }
    /*****起点在元素下端*****/
    if (startpoint.position == "B") {
        var vs = new KeyPoint(startpoint.x, startpoint.y + d, 'key');
        keypoints[1] = vs;
        //终点在元素上端
        if (endpoint.position == "T") {
            var ve = new KeyPoint(endpoint.x, endpoint.y - d, 'key');
            //终点在起点上面
            if (endpoint.y < startpoint.y) {
                var cx = getCenterPoint(vs,ve).x;
                keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                keypoints[3] = new KeyPoint(cx, ve.y, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            //终点在起点下面
            else if (endpoint.y > startpoint.y) {
                var cy = getCenterPoint(vs,ve).y;
                keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素右端
        if (endpoint.position == "R") {
            var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
            //终点在起点右边
            if (endpoint.x > startpoint.x) {
                keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点左边
            else if (endpoint.x < startpoint.x) {
                //终点在起点上边
                if (endpoint.y < startpoint.y) {
                    var cx = getCenterPoint(vs, endpoint).x;
                    keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                    keypoints[3] = new KeyPoint(cx, ve.y, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                //终点在起点下边
                if (endpoint.y > startpoint.y) {
                    keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
            }
            else{
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素下端
        if (endpoint.position == "B") {
            var ve = new KeyPoint(endpoint.x, endpoint.y + d, 'key');
            //终点在起点上面
            if (endpoint.y < startpoint.y) {
                keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点下面
            else if (endpoint.y > startpoint.y) {
                keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素左端
        if (endpoint.position == "L") {
            var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
            //终点在起点左边
            if (endpoint.x < startpoint.x) {
                keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点右边
            else if (endpoint.x > startpoint.x) {
                //终点在起点上边
                if (endpoint.y < startpoint.y) {
                    var cx = getCenterPoint(vs, endpoint).x;
                    keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                    keypoints[3] = new KeyPoint(cx, ve.y, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
                //终点在起点下边
                if (endpoint.y > startpoint.y) {
                    keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
    }
    /*****起点在元素左边*****/
    if(startpoint.position == "L"){
        var vs = new KeyPoint(startpoint.x - d, startpoint.y, 'key');
        keypoints[1] = vs;
        //终点在元素上边
        if (endpoint.position == "T") {
            var ve = new KeyPoint(endpoint.x, endpoint.y - d, 'key');
            //终点在起点上边
            if (endpoint.y < startpoint.y) {
                keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点下边
            else if (endpoint.y > startpoint.y) {
                //终点在起点左边
                if (endpoint.x < startpoint.x) {
                    keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
                //终点在起点右边
                if (endpoint.x > startpoint.x) {
                    var cy = getCenterPoint(vs, endpoint).y;
                    keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                    keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素右边
        if (endpoint.position == "R") {
            var ve = new KeyPoint(endpoint.x + d, endpoint.y, 'key');
            //终点在起点左边
            if (endpoint.x < startpoint.x) {
                var cx = getCenterPoint(vs, ve).x;
                keypoints[2] = new KeyPoint(cx, vs.y, 'key');
                keypoints[3] = new KeyPoint(cx, ve.y, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            //终点在起点右边
            else if (endpoint.x > startpoint.x) {
                var cy = getCenterPoint(vs, ve).y;
                keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                keypoints[4] = ve;
                keypoints[5] = endpoint;
                return(keypoints);
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素下边
        if (endpoint.position == "B") {
            var ve = new KeyPoint(endpoint.x, endpoint.y + d, 'key');
            //终点在起点下边
            if (endpoint.y > startpoint.y) {
                keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点上边
            else if (endpoint.y < startpoint.y) {
                //终点在起点左边
                if (endpoint.x < startpoint.x) {
                    keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                    keypoints[3] = ve;
                    keypoints[4] = endpoint;
                    return(keypoints);
                }
                //终点在起点右边
                if (endpoint.x > startpoint.x) {
                    var cy = getCenterPoint(startpoint, endpoint, 'key').y;
                    keypoints[2] = new KeyPoint(vs.x, cy, 'key');
                    keypoints[3] = new KeyPoint(ve.x, cy, 'key');
                    keypoints[4] = ve;
                    keypoints[5] = endpoint;
                    return(keypoints);
                }
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
        //终点在元素左边
        if (endpoint.position == "L") {
            var ve = new KeyPoint(endpoint.x - d, endpoint.y, 'key');
            //终点在起点左边
            if (endpoint.x < startpoint.x) {
                keypoints[2] = new KeyPoint(ve.x, vs.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            //终点在起点右边
            if (endpoint.x > startpoint.x) {
                keypoints[2] = new KeyPoint(vs.x, ve.y, 'key');
                keypoints[3] = ve;
                keypoints[4] = endpoint;
                return(keypoints);
            }
            else {
                keypoints[2] = ve;
                keypoints[3] = endpoint;
                return(keypoints);
            }
        }
    }
}

//重新绘制连接线
//method reDrawConnector(object)
function reDrawConnector(obj) {
    'use strict';
    for (var i in connectors) {
        var CoType = connectors[i].CoType;
        //移动连接线起点的元素时
        if (connectors[i].headId == obj.id) {
            //重获起点坐标
            var po = [];
            po = GetPointFromObj(obj, connectors[i].startPo);
            var startpoint = new KeyPoint(po[0], po[1], connectors[i].startPo);
            //取得终点元素，指定终点坐标
            var target = getObjectById(connectors[i].endId);
            var poe = [];
            poe = GetPointFromObj(target, connectors[i].endPo);
            var endpoint = new KeyPoint(poe[0], poe[1], connectors[i].endPo);

            var keypos = [];
            keypos = getKeyPoints(startpoint,endpoint);
            //删除原连接线，增加新连接线
            canvas.remove(connectors[i]);
            connectors.splice(i,1);
            var ve = strokeConnector(keypos);
            ve.set({
                headId:obj.id,
                endId:target.id,
                startPo:startpoint.position,
                endPo:endpoint.position,
                CoType:CoType
            });
            setConnectorClear(ve);
            canvas.add(ve);
            connectors.push(ve);
            canvas.renderAll();
            canvas.sendToBack(ve);
            reLoadTagsCollection();										//刷新节点集合选项
        }
        //当移动连接线终点的元素时
        else if (connectors[i].endId == obj.id) {
            //获取终点坐标
            var poe = [];
            poe = GetPointFromObj(obj, connectors[i].endPo);
            var endpoint = new KeyPoint(poe[0], poe[1], connectors[i].endPo);
            //取得起点连接元素，获取起点坐标
            var target = getObjectById(connectors[i].headId);
            var po = [];
            po = GetPointFromObj(target, connectors[i].startPo);
            var startpoint = new KeyPoint(po[0], po[1], connectors[i].startPo);
            var keypos = [];
            keypos = getKeyPoints(startpoint,endpoint);
            //删除当前，绘制最新
            canvas.remove(connectors[i]);
            connectors.splice(i,1);
            var ve = strokeConnector(keypos);
            ve.set({
                headId:target.id,
                endId:obj.id,
                startPo:startpoint.position,
                endPo:endpoint.position,
                CoType:CoType
            });
            canvas.add(ve);
            setConnectorClear(ve);
            connectors.push(ve);
            canvas.renderAll();
            canvas.sendToBack(ve);
            reLoadTagsCollection();										//刷新节点集合选项
        }
    }
}

//根据id获取查找元素
//obj getObjectById(num)
function getObjectById(id) {
    'use strict'
    var objGet = false;
    for (var i in objs) {
        if (objs[i].id == id) {
            objGet = objs[i];
        }
    }
    return objGet;
}


/*---------------------------------------------------------------------------------------------------------------------*/




/*------------------------------------------------连接线辅助提示点功能块-----------------------------------------------*/
//判断并返回鼠标下的元素
//Obj getObjectUnderMouse(obj)
function getObjectUnderMouse(point) {
    'use strict';
    if (objs.length > 0) {
        for (var i in objs) {
            if (PointInObject(point.x, point.y, objs[i])) {
                return(objs[i]);
            }
        }
    }
}

//初始化连接提示点
function initHelpPoint() {
    'use strict';
    helppoint = new fabric.Circle({
        opacity:0.5,
        left:20,
        top:20,
        radius:9,
        stroke:'#999',
        strokeWidth:5,
        selectable:false,
        id:'cp',
        visible:false
    });
    canvas.add(helppoint);
}

//显示连接提示点
function showConnectHelpPoint(point) {
    'use strict';
    //定义提示点样式
    var target = getObjectUnderMouse(point);						//获取当前鼠标坐标下的对象
    if(target){
        var po = [];
        po = whitchPointInObject([point.x, point.y], target);			//获取当前鼠标点位于元素的哪个连接点
        var str = whitchPointInObjectStr([point.x, point.y], target);	//获取当前鼠标坐标位于元素的那个连接点描述

        canvas.bringToFront(helppoint);								//将提示点放在最前端
        if(str == 'L'){
            var p = new fabric.Point(po[0] + 5, po[1]);
        }
        if(str == 'T'){
            var p = new fabric.Point(po[0], po[1] + 5);
        }
        if(str == 'R'){
            var p = new fabric.Point(po[0] - 5, po[1]);
        }
        if(str == 'B'){
            var p = new fabric.Point(po[0], po[1] - 5);
        }
        helppoint.setPositionByOrigin(p, 'center', 'center');		//将提示点贴在该连接点上
        helppoint.setVisible(true);									//提示点显示
    }
    else{
        return;
    }
}

//隐藏连接提示点
function hideHelpPoint() {
    'use strict';
    helppoint.setVisible(false);
    helppoint.sendToBack();
}
/*---------------------------------------------------------------------------------------------------------------------*/




/*---------------------------------------------读取、生成工作流配置功能块------------------------------------------------*/
//根据名称获取Url中某个参数的值
function GetUrlParam(pname) {
    var reg = new RegExp("(^|&)" + pname + "=([^&]*)(&|$)");
    var r = window.location.search.substr(1).match(reg);
    if (r != null) return decodeURI(r[2]);
    return null;
}

//寻找节点上下流程节点获取id
//Array findPreOrNextObj(String,Number)	str = pre || next
function findPreOrNextObj(str, id) {
    'use strict';
    //查询获取后置节点id
    if(str == 'next'){
        var nextids = [];		//存储后置节点的id
        for (var i in connectors) {
            if (connectors[i].headId == id) {
                nextids.push(connectors[i].endId);
            }
        }
        return(nextids);
    }
    //查询获取前置节点id
    if (str == 'pre') {
        var preids = [];
        for (var i in connectors) {
            if (connectors[i].endId == id) {
                preids.push(connectors[i].headId);
            }
        }
        return(preids);
    }
}

//获取元素前后连接线
//Array getConsForObj(string, num)
function getConsForObj(str, id){
    'use strict';
    var cons = [];
    //获取前置连接线
    if (str == 'pre') {
        for (var i in connectors){
            if (connectors[i].endId == id) {
                cons.push(connectors[i]);
            }
        }
        return(cons);
    }
    //获取后置连接线
    if (str == 'next') {
        for (var i in connectors) {
            if (connectors[i].headId == id) {
                cons.push(connectors[i]);
            }
        }
        return(cons);
    }
}

//查询该元素的前后连接点位置信息
function getConPoById(str, id){
    'use strict';
    var cons = [];
    cons = getConsForObj(str, id);		//获取指定连接线
    //获取前置连接点位置信息
    if (str == 'pre') {
        var prepos = [];
        for (var i in cons) {
            prepos.push(cons[i].endPo);
        }
        return(prepos);
    }
    //获取后置连接点位置信息
    if (str == 'next') {
        var endpos = [];
        for (var i in cons) {
            endpos.push(cons[i].startPo);
        }
        return(endpos);
    }
}

//从服务器获取配置XML，并解析
function getXMLFromServer(){
    'use strict';
    var datas = {
        "id":workFlowId,
    };
    ibcpAjax.Select(workFlowCheckUrl,datas,false,function(result){
        txt = result.data.resource;
        if(txt == ""){
            return;
        }else{
            loadConfigInfo(txt);
        }
    });
}

//解析XML内容，生成工作流
function loadConfigInfo(text) {
    'use strict';
    try{
        var xmlDoc = loadXMLString(text);
        var tags = xmlDoc.getElementsByTagName('targets')[0].childNodes;	//选取所有节点元素配置
        if (tags.length == 0) {
            return;
        }
        for (var i = 0; i < tags.length; i++) {
            //Start节点
            if (tags[i].getAttribute('objType') == 'Start') {								//判断节点类型
                Start();																	//绘制对应的节点种类
                var target = objs[objs.length - 1];											//找到当前绘制的节点
                //对应到配置中的位置信息
                var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
                //设置节点属性
                target.set({
                    id:tags[i].getAttribute('id'),
                    stepname:tags[i].getAttribute('stepname'),
                });
                target.setPositionByOrigin(po, 'center', 'center');
                //设置节点文字内容
                var Text = findTextInGroup(target);
                Text.set({
                    text:target.stepname,
                    fontSize:FontSize
                });
                centerTextForTarget(target);
                canvas.renderAll();
            }
            //Task节点
            if (tags[i].getAttribute('objType') == 'Task') {
                drawRectangleCmd();
                var target = objs[objs.length - 1];
                var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
                target.set({
                    id:tags[i].getAttribute('id'),
                    number:tags[i].getAttribute('number'),
                    stepId:tags[i].getAttribute('stepId'),
                    stepname:tags[i].getAttribute('stepname'),
                    version:tags[i].getAttribute('version'),
                    stepCode:tags[i].getAttribute('stepCode'),
                    workId:tags[i].getAttribute('workId'),
                    workCode:tags[i].getAttribute('workCode'),
                    workName:tags[i].getAttribute('workName'),
                    workType:tags[i].getAttribute('workType')
                });
                target.setPositionByOrigin(po, 'center', 'center');
                var Text = findTextInGroup(target);
                Text.set({
                    text:target.number.toString() + "-" + target.stepname.toString(),
                    fontSize:FontSize
                });
                centerTextForTarget(target);
                canvas.renderAll();
            }
            //Gate节点
            if (tags[i].getAttribute('objType') == 'Gate') {
                drawDiamondCmd();
                var target = objs[objs.length - 1];
                var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
                target.set({
                    id:tags[i].getAttribute('id'),
                    formula:tags[i].getAttribute('formula')
                });
                target.setPositionByOrigin(po, 'center', 'center');
                canvas.renderAll();
            }
            //End节点
            if (tags[i].getAttribute('objType') == 'End') {
                End();
                var target = objs[objs.length - 1];
                var po = new fabric.Point(tags[i].getAttribute('locx') * 1, tags[i].getAttribute('locy') * 1);
                target.set({
                    id:tags[i].getAttribute('id'),
                    stepNamne:tags[i].getAttribute('stepname'),
                });
                target.setPositionByOrigin(po, 'center', 'center');
                var Text = findTextInGroup(target);
                Text.set({
                    text:tags[i].getAttribute('stepname'),
                    fontSize:FontSize
                });
                centerTextForTarget(target);
                canvas.renderAll();
            }
        }
        //强制刷新画布
        freshCanvas();
        //连接线读取生成
        var cons = xmlDoc.getElementsByTagName('connectors')[0].childNodes;
        for (var i = 0; i < cons.length; i++) {
            if (cons[i].getAttribute('objType') == 'Connector') {								//连接线线种选择
                var pretarget = getObjectById(cons[i].getAttribute('headId'));		//上一个连接节点
                var nexttarget = getObjectById(cons[i].getAttribute('endId'));		//下一个连接节点
                var po = [];
                po = GetPointFromObj(pretarget,cons[i].getAttribute('startPo'));	//上一个连接点
                var startpoint = new KeyPoint(po[0], po[1], cons[i].getAttribute('startPo'));
                var epo = [];
                epo = GetPointFromObj(nexttarget, cons[i].getAttribute('endPo'));	//下一个连接点
                var endpoint = new KeyPoint(po[0], po[1], cons[i].getAttribute('startPo'));
                var keypoints = [];
                keypoints = getKeyPoints(startpoint,endpoint);
                var connector = strokeConnector(keypoints);
                connector.set({
                    startPo:cons[i].getAttribute('startPo'),	//连接线起点坐标相对元素位置
                    endPo:cons[i].getAttribute('endPo'),		//连接线终点坐标相对元素位置
                    headId:cons[i].getAttribute('headId'),				//连接线起点连接元素id
                    endId:cons[i].getAttribute('endId'),						//连接线终点连接元素id
                    objType:cons[i].getAttribute('objType'),						//对象种类
                    CoType:cons[i].getAttribute('CoType')							//连接线种类
                });
                canvas.add(connector);
                connectors.push(connector);
            }
        }
        //重绘所有连接线
        for (var i in objs) {
            reDrawConnector(objs[i]);
        }
        //将Id指向当前最大
        Id = getMaxId() + 1;
        configInfo();                   //记录当前配置
    }
    catch(e) {
        ibcpLayer.ShowMsg('解析失败：程序数据格式错误！');
    }
}

//XML字符串解析
function loadXMLString(text) {
    //if (window.DOMParser){
    var parser = new DOMParser();
    xmlDoc = parser.parseFromString(text, "text/xml");
    return xmlDoc;
}

//将XML DOM转化成字符串
function parseXML(doc){
    'use strict';
    var oSerializer = new XMLSerializer();
    return oSerializer.serializeToString(doc, 'text/xml');
}

//记录配置信息
function configInfo(save){
    'use strict';
    //loadXMLString(txt);
    txt = '<?xml version="1.0" encoding="utf-8"?>';
    txt = txt + '<ibatch>';
    txt = txt + '<targets>';
    //节点部分
    for (var i in objs){
        var id = objs[i].id,                        //节点id
            number = objs[i].number,				//节点序号
            objType = objs[i].objType,              //节点类型
            locx = GetPointFromObj(objs[i],'C')[0], //节点X坐标
            locy = GetPointFromObj(objs[i],'C')[1], //节点Y坐标
            stepId = objs[i].stepId ? objs[i].stepId : null,                	//节点实体id（程序id）
            stepname = objs[i].stepname,            							//节点实体名称（程序名称）
            stepCode = objs[i].stepCode ? objs[i].stepCode : null,            //节点实体代码（程序代码）
            version = objs[i].version ? objs[i].version : null,              //节点实体版本（程序版本）
            formula = objs[i].formula ? objs[i].formula : null,       //判断项公式
            workId = objs[i].workId ? objs[i].workId : null,            //工位（组）id
            workCode = objs[i].workCode ? objs[i].workCode : null,    //工位（组）代码
            workName = objs[i].workName ? objs[i].workName : null,    //工位（组）名称
            workType = objs[i].workType ? objs[i].workType : null;		//工位种类

        txt = txt + '<target id="' + id + '" number="' + number + '" objType="' + objType + '" locx="' + locx + '" locy="' + locy + '" stepId="' + stepId + '" stepname="' + stepname + '" stepCode="' + stepCode + '" version="' + version +'" formula="' + formula + '" workId="' + workId + '" workCode="' + workCode + '" workName="' + workName + '" workType="' + workType + '"></target>';
    }
    txt = txt + '</targets>';
    txt = txt + '<connectors>';
    //连接线部分
    for (var i in connectors){
        txt = txt + '<connector objType="' + connectors[i].objType + '" CoType="' + connectors[i].CoType + '" headId="' + connectors[i].headId.toString() + '" endId="' + connectors[i].endId.toString() + '" startPo="' + connectors[i].startPo + '" endPo="' + connectors[i].endPo + '" ></connector>';
    }
    txt = txt + '</connectors>';
    txt = txt + '</ibatch>';
    if(save){
        //检查数据是否合法
        var propotyCheck = ibcpFlowCheck.errorCheck();
        if(propotyCheck == false){
            ibcpLayer.ShowMsg("请完善流程图信息！");
            return;
        };

        signPath = '../../Public/';
        CallSign(100, function(sid) {
            var datas = {
                "id":workFlowId,
                "resource":txt,
                "sid":sid
            }
            ibcpAjax.Insert(workFlowEditUrl,datas,false,function(result){
                console.log(datas.resource);
                SignCancel();
                ibcpLayer.ShowOK("保存成功！");
                $('#SignDiv').html("");
                window.parent.LoadCraftPic(workFlowId);
            });
        });
    }
}
/*--------------------------------------------------------------------------------------------------------------------*/




/*---------------------------------------------画面格式整理功能块-------------------------------------------------------*/
//将当前节点贴附到网格焦点上
function arrangeTarget(target) {
    'use strict';
    var po = [];
    po = GetPointFromObj(target,'C');
    var x = searchNearNum(po[0],5);
    var y = searchNearNum(po[1],5);
    var point = new fabric.Point(x,y);
    target.setPositionByOrigin(point, 'center', 'center');
    canvas.renderAll();
    reDrawConnector(target);
    freshCanvas();
}

//判断数字和某数的倍数相近
function searchNearNum(num, stdnum){
    'use strict';
    var residue = num % stdnum;
    var quotient = parseInt(num / stdnum);
    if (residue < (stdnum / 2)) {
        return(num - residue);
    }
    else {
        return((quotient + 1) * stdnum);
    }
}

//刷新节点
function freshCanvas() {
    'use strict';
    //通过缩放刷新节点位置
    var point = new fabric.Point(0, 0);
    canvas.zoomToPoint(point, zoom - 0.1);
    canvas.zoomToPoint(point, zoom);
}

//获取鼠标坐标
function getMousePos(event) {
    var e = event || window.event;
    return {
        'x':e.clientX,
        'y':clientY
    }
}

//显示缩放比例
function showZoomData() {
    'use strict';
    var $box = $('#zoombox');
    var $show = $('#zoomshow');
    $show.html(parseInt(zoom * 100) + "%");			//将缩放倍数转换成百分比形式
    //计算工作区中心
    var x = ($('#canvasbox').width() - $box.width()) / 2;
    var y = ($('#canvasbox').height() - $box.height()) / 2;
    $box.attr('style','display:""');
    $box.css({
        left:x,
        top:y
    });
    //两秒消失
    window.setTimeout( function() {
        $box.attr('style','display:none')
    }, 2000);
}

//设置按钮选中状态
function setButtonSelected(btn, stage) {
    'use strict';
    if (stage == true) {
        btn.removeClass('toolBtn');
        btn.addClass('down');
    }
    if (stage == false) {
        btn.addClass('toolBtn');
        btn.removeClass('down');
    }
}

//清除属性面板内容
function clearInstallPage() {
    'use strict';
    $('input[wftype]').each(function(){
        $(this).val('');
        $(this).attr('readonly', true);
    });
    $('textarea[wftype]').each(function(){
        $(this).val('');
        $(this).attr('readonly', true);
    });
    $('select[wftype]').each(function(){
        $(this).attr('disabled', true);
    });
    $('button[wftype]').each(function(){
        $(this).attr('disabled', true);
    });
}

//页面最大化
function Max(){
    'use strict';
    var index = parent.layer.getFrameIndex(window.name);
    parent.layer.iframeAuto(index);
}


//将节点中的文字居中对齐
function centerTextForTarget(target){
    'use strict';
    var Text = findTextInGroup(target);
    var Point = new fabric.Point(0,0);
    Text.setPositionByOrigin(Point, "center", "center");
    canvas.renderAll();
}
/*---------------------------------------------------------------------------------------------------------------------*/




/*--------------------------------------弹出层功能块------------------------------------------------------------*/
//弹出选择节点画面
function stepSelectPage(title, url, width, height){
    'use strict';
    var $page = $('<div id="Step_Select_Box" style="position:absolute;"></div>');
    var $cont = $('<div id="Step_Select_Page" style="position:absolute;border-radius:5px;"><div style="padding-left:10px;padding-top:5px;margin:0;background-color:#F8F8F8"><h4>'+ title + '</h4></div><div id="Step_Select_Page_Content" style="width:100%;"></div></div>');
    var that = this;
    this.show = function(callback){
        callback(that);
        $('body').after($page);
        $('body').after($cont);
        var $width = $(window).width();
        var $height = $(window).height();
        var $left = ($width - width) / 2;
        var $top = ($height - height) / 2;

        $('#Step_Select_Box').css('width', $(window).width());
        $('#Step_Select_Box').css('height', $(window).height());
        $('#Step_Select_Page').css('width', width);
        $('#Step_Select_Page').css('height', height);

        //将弹出层放在屏幕中间
        $('#Step_Select_Page').css('left', $left);
        $('#Step_Select_Page').css('top', $top);

        //加载弹出层页面内容
        $('#Step_Select_Page_Content').load(url,null);
        $('#Step_Select_Page').css('opacity', 1);
        $('#Step_Select_Page').css('z-index', 1001);

        $(window).resize(function(){
            $('#Step_Select_Box').css('width', $(window).width());
            $('#Step_Select_Box').css('height', $(window).height());
            $('#Step_Select_Page').css('left', ($(window).width() - width) / 2);
            $('#Step_Select_Page').css('top', ($(window).height() - height) / 2);
        });
    };

    this.close = function(){
        $page.remove();
        $cont.remove();
    }
}
/*-----------------------------------------------------------------------------------------------------------*/



/*---------------------------------------------撤销功能块-------------------------------------------------------*/
//时时记录状态信息
function configOnTime() {
    'use strict';
    if (revocation == false) {
        configInfo();
        if (configStore.length > 20) {
            configStore.splice(0,1);
        }
        configStore.push(txt);
    }else {
        return;
    }
}

//撤销
function revocationInfo() {
    'use strict';
    if (configStore.length >= 2) {
        revocation = true;
        configStore.splice(configStore.length - 1, 1);
        var text = configStore[configStore.length - 1];
        text = text.replace(/[\n]/ig, '');															//格式化XML字符串
        ClearPage();																				//清空当前工作台内容
        loadConfigInfo(text);
        revocation = false;
        Id = getMaxId() + 1;																		//将id指针指向当前最大后一位
    }else {
        configStore = [];
        revocation = false;
        return;
    }
}

//获取当前最大id
function getMaxId() {
    'use strict';
    var maxId = 0;
    for(var i in objs){
        if(objs[i].id < 99999999){
            maxId = Math.max(maxId, objs[i].id);
        }
    }
    return maxId;
}
/*--------------------------------------------------------------------------------------------------------------*/


/*----------------------------------------查看流程功能块----------------------------------------------------------*/
/*------------------------These functions server for WorkFlowCheck.html------------------------------------------*/
//固定所有节点不可拖动和缩放
function fixAllTarget(){
    'use strict';
    for(var i in objs){
        objs[i].set({
            lockMovementX:true,
            lockMovementY:true,
            lockScalingX:true,
            lockScalingY:true
        });
    }
}
/*----------------------------------------------------------------------------------------------------------------*/




/*-----------------------------------------------------步骤编辑功能块--------------------------------------------------*/
//显示步骤选择画面
function showStepSelect(){
    'use strict';
    var url = "ProcedureAdd.html";
    stepAddDivIndex = ibcpLayer.ShowDiv(url, '输入工序信息', '500px', '310px', function(){
        initProcedureAdd(stepAddDivIndex);
    });
}

//关闭步骤选择画面
function initProcedureAdd(stepAddDivIndex){
    'use strict';
    //取消按钮事件
    $("#AddProcedure_Cancel_Btn").on('click', function(){
        ibcpLayer.Close(stepAddDivIndex);
    });
}

//公式提交按钮功能
function formulaSubmit(){
    'use strict';
    var target = getObjectById(ActiveId);
    var cont = document.getElementById('WF_Formula').value;
    if (target.objType == "Gate") {
        target.set({
            formula:cont
        });
    }
}

//根据点击元素类型设置属性面板状态
function setEditStateByType(type){
    'use strict';
    //只针对开始和结束显示信息
    if (type == "Start" || "End"){
        $('[bcsgrp]').css('display','none');
        $('[bcsgrp="Info-Task"]').css('display','inline');
    }
    //只针对步骤开放选择步骤操作
    if (type == "Task") {
        $('#WF_Edit').removeAttr('disabled');
        $('tr[bcsgrp]').css('display','none');
        $('tr[bcsgrp="Info-Task"]').css('display','inline');
    }

    //只针对连接线开放选择链接种类操作
    if (type == "Connector"){
        $('tr[bcsgrp]').css('display','none');
        $('tr[bcsgrp="Info-Connector"]').css('display','inline');
        if(PageName == "edit"){
            $('#WF_CoType').removeAttr('disabled');
        }
    }

    //只针对判断项开放公式输入信息和程序选择
    if (type == "Gate") {
        $('tr[bcsgrp]').css('display','none');
        $('tr[bcsgrp="Info-Gate"]').css('display','inline');
        if(PageName == "edit"){
            $('#WF_Formula').removeAttr('readonly');
            $('#WF_FormulaSubmit').removeAttr('disabled');
        }
    }

    if (type == "clear") {
        $('tr[bcsgrp]').css('display','none');
        $('#WF_Edit').attr('disabled', true);
        $('#WF_CoType').attr('disabled', true);
        $('#WF_Formula').attr('readonly', true);
    }
}

//显示属性面板信息
//method showInfo(obj)
function showInfo(target) {
    'use strict';
    try{
        //开始节点信息
        if(target.id == 0){
            $('#WF_Name').val(target.stepname);						//显示开始名称
        }
        //结束节点信息
        else if(target.id == 99999999){
            $('#WF_Name').val(target.stepname);						//显示结束名称
        }
        //步骤项信息
        else if(target.objType == "Task"){
            $('#WF_Code').val(target.stepCode);						//读取节点代码
            $('#WF_Name').val(target.stepname);						//读取节点名称
            $('#WF_Version').val(target.version);					//读取程序版本
            $('#WF_WorkCode').val(target.workCode);                 //读取工位代码
            $('#WF_WorkName').val(target.workName);                 //读取工位名称
        }
        //判断项信息
        else if(target.objType == "Gate"){
            $('#WF_Formula').val(target.formula);					//读取判断公式
        }
        //连接线信息
        else if(target.objType == "Connector"){
            if(target.CoType == "开始-开始"){						//读取连接线链接类型
                $("#WF_CoType").val(0);
            }else if(target.CoType == "结束-开始"){
                $("#WF_CoType").val(1);
            }
            var headtarget = getObjectById(target.headId);			//获取前连接点
            var endtarget = getObjectById(target.endId);			//获取后连接点
            $('#WF_CoStart').val((headtarget.objType == "Gate") ? "判断项" : headtarget.stepname);				//显示前连接点
            $('#WF_CoEnd').val((endtarget.objType == "Gate") ? "判断项" : endtarget.stepname);					//显示后连接点
        }else {
            return;
        }
        setEditStateByType(target.objType);

    }catch(e){
        alert(e);
    }
}


//设置连接线种类
function selectCoType(id){
    'use strict';
    var target = ActiveConnector;
    if (target.objType == 'Connector') {
        target.CoType = $('#'+ id).find("option:selected").text();
        setConnectorClear(target);											//设置当前属性的连接线样式
        reLoadTagsCollection();												//刷新节点集合选项
    }else{
        return;
    }
}

//寻找Group中text
function findTextInGroup(target) {
    'use strict';
    for(var i = 0; i >= 0; i ++) {
        if (target.item(i).type == 'text') {
            return(target.item(i));
        }
    }
}

//将步骤选择列表中的信息填入当前选中元素中
function selectProcedureInfo(wfprcode, wfprname, wfprversion, wfprid, wfwkcode, wfwkname, wfwkid, wfwktype, stepNumber){
    'use strict';
    if(wfprcode == null || wfprname == null || wfprversion == null) return;
    var target = getObjectById(ActiveId);
    if (target.objType == 'Task' || 'Gate') {
        target.set({
            stepId:wfprid,
            stepCode:wfprcode,
            stepname:wfprname,
            version:wfprversion,
            workCode:wfwkcode,
            workName:wfwkname,
            workId:wfwkid,
            workType:wfwktype,
            number:stepNumber
        });
        var Text = findTextInGroup(target);
        Text.set({
            text:stepNumber.toString() + "-" + wfprname.toString(),
            fontSize:FontSize
        });
        centerTextForTarget(target);					//文字居中显示
        ibcpLayer.Close(stepAddDivIndex);
    }
    reLoadTagsCollection();								//刷新节点集合选项
    showInfo(target);
}

//刷新节点集合中的信息
function reLoadTagsCollection(){
    'use strict';
    clearSelectOptions('Current_Target');
    getAllTagsForSelector();
    //getAllConnectorsOptions();
}

//将工作流所有节点写入节点集合中
function getAllTagsForSelector(){
    'use strict';
    var objList = [];
    for(var i in objs){
        if(objs[i].objType == 'Task'){
            objList.push([String(objs[i].stepCode) + "--" + objs[i].stepname, objs[i].id]);
        }
        if(objs[i].objType == 'Gate'){
            var ids = [];
            ids = findPreOrNextObj('pre', objs[i].id);						//获得上一个节点的id集合（这里为判断节点，入口应为一个）
            var preTag = getObjectById(ids[0]);								//根据id找到入口节点
            if(preTag)	objList.push([String(preTag.stepCode) + "--" + preTag.stepname + "【判断项】", objs[i].id]);
        }
    }
    var sObjList = objList.sort();
    for( var i in sObjList){
        insertOption('Current_Target', sObjList[i][1], sObjList[i][0]);
    }
}

//清空工作流集合下拉框
function clearAllOptions(selectId){
    'use strict';
    var selector = document.getElementById(selectId);
    for (var i = 0; i < selector.options.length; i++){
        selector.options[i].remove();
    }
}

//根据value删除指定选项
function delectAOption(selectId,value){
    'use strict';
    var selector = document.getElementById(selectId);
    for (var i = 0; i < selector.options.length; i++){
        if(selector.options[i].value == value){
            selector.options[i].remove();
        }
    }
}

//向select中添加一条option
function insertOption(selectId, value, text){
    'use strict';
    var select = document.getElementById(selectId);
    select.options.add(new Option(text, value));
}

//查找select中是否含有指定value
function checkValueInSelect(selectId, value){
    'use strict';
    var isExit = false;
    var select = document.getElementById(selectId);
    for (var i = 0;i < select.options.length; i++){
        if (select.options[i].value == target.id) {
            isExit = true;
            break;
        }
    }
    return isExit;
}

//根据value设置select当前选中值
function setSelectSelected(selectId, value){
    'use strict';
    var select = document.getElementById(selectId);
    for(var i = 0; i < select.options.length; i++){
        if(value == select.options[i].value){
            select.options[i].selected = true;
        }
    }
}

//清空select中的动态项
function clearSelectOptions(selectId){
    'use strict';
    var select = document.getElementById(selectId);
    select.innerHTML = "";
}

//显示当前选中节点在节点结合中的选项
function showCurrentTatgetSelect(object){
    'use strict';
    if(object.objType == 'Connector'){
        var val = String(object.headId) + "-" + String(object.endId);
        setSelectSelected('Current_Target', val);
    }
    if(object.objType == 'Start' || 'End' || 'Task' || 'Gate'){
        setSelectSelected('Current_Target', object.id);
    }
}

//清空当前元素展示
function currentTargetClear(){
    'use strict';
    $('#Current_Target').html("");
}

//获取select当前选中的value
function getCurrentOption(selectId){
    'use strict';
    var select = document.getElementById(selectId);
    for(var i = 0; i < select.options.length; i++){
        if(select.options[i].selected == true){
            return select.options[i].value;
        }
    }
}

//节点集合下拉框选择事件
function initCurrentTargetSelector(){
    'use strict';
    var select = document.getElementById('Current_Target');
    select.setAttribute('onfocus','fixEditor()');
    select.setAttribute('onblur','editEditor()');
    select.onchange = function(){
        var val = getCurrentOption('Current_Target');
        var target = getObjectById(val);
        if(target){
            clearInstallPage();
            showInfo(target);
            selectCleared();
            setObjectSelected(target);
        }
        else{
            for(var i in connectors){
                var ids = String(connectors[i].headId) + "-" + String(connectors[i].endId);
                if(ids == val){
                    clearInstallPage();
                    showInfo(connectors[i]);
                    selectCleared();
                    setConnectorSelected(connectors[i]);
                }
            }
        }
    }
}
//停止键盘监听
function fixEditor(){
    Edit = 0;
}
//允许键盘监听
function editEditor(){
    Edit = 1;
}

//模拟节点选中状态样式
function setSelectedTag(target){
    'use strict';
    if(target){
        setTargetSelected(target, 1);
    }

    if(target == null){
        for(var i in objs){
            setTargetSelected(objs[i], 2);
        }
        for(var i in connectors){
            setConnectorClear(connectors[i]);
        }
    }
    canvas.renderAll();
}


/*---------------------------------------------------------------------------------------------------------------------*/






/*---------------------------------------------检查、限制功能模块--------------------------------------------------------*/
/*通过类型检查是否存在元素，返回bool值，存在返回true*/
function checkUpTargetByType(type){
    'use strict';
    if (type == 'Start') {
        if (getObjectById(0)) {
            return(true);
        }else{
            return(false);
        }
    }
    if (type == 'End') {
        if (getObjectById(99999999)) {
            return(true);
        }else{
            return(false);
        }
    }
}

/*判断是否保存*/
function savedCheck(){
    'use strict';
    var precon;
    var datas = {
        "id":workFlowId,
    }
    ibcpAjax.Select(workFlowCheckUrl,datas,false,function(result){
        precon = result.data.resource;
    });
    configInfo(null);
    if (precon == txt) {
        return(false);					//不需要保存
    }else{
        return(true);					//需要保存
    }
}


/*画面关闭事件*/
function initUnloadEvent(){
    'use strict';
    layer.confirm('系统检测到您最近的工作没有进行保存，是否在关闭前进行保存？', {
        title: '提示',
        zIndex: layer.zIndex,
        btn: ['保存', '关闭'],
        yes: function (index) {
            ConfigInfo();
        },
        btn2: function(index){
            var index = parent.layer.getFrameIndex(window.name); //获取窗口索引
            parent.layer.close(index);
        }
    });
}

/*根据指定属性查找元素*/
function getObjectByProp(prop, value){
    'use strict';
    var searchTargets = [];
    for(var i in objs){
        if(objs[i][prop] == value){
            searchTargets.push(objs[i]);
        }
    }
    return searchTargets;
}
/*----------------------------------------------------------------------------------------------------------------------*/








/*-------------------------------------------------元素样式改变功能块---------------------------------------------------*/
//设置节点选中样式
function setObjectSelected(target){
    'use strict';
    if(target.objType != "Connector"){
        target.set({
            opacity: 0.3
        });
    }
    canvas.renderAll();
    ActiveId = target.id;
}

//设置元素还原样式
function setObjectCleared(target){
    'use strict';
    target.set({
        opacity: 1
    });
    canvas.renderAll();
    ActiveId = null;
}

//设置连接线选中样式
function setConnectorSelected(connector){
    'use strict';
    connector.set({
        stroke: 'red'
    });
    canvas.renderAll();
    ActiveConnector = connector;
}

//设置连接线清除选择样式
function setConnectorClear(connector){
    'use strict';
    if(connector.CoType == "开始-开始"){
        connector.set({
            stroke: 'blue'
        });
    }else if(connector.CoType == "结束-开始"){
        connector.set({
            stroke: 'black'
        });
    }
    canvas.renderAll();
    ActiveConnector = null;
}


//清除选中状态
function selectCleared(){
    'use strict';
    for(var i in objs){
        setObjectCleared(objs[i]);
    }
    for(var i in connectors){
        setConnectorClear(connectors[i]);
    }
    canvas.renderAll();
}

/*----------------------------------------------------------------------------------------------------------------------*/
//**********************************
/*-----This area is for ready-----*/
//**********************************



//*********************************
/*-----This area is for test-----*/
//*********************************
//Test
function Test(){
    'use strict';
    try{
        var starttarget = getObjectById(0);
        var endtarget = getObjectById(1);
        var startpo = getOptimalConnection(starttarget, endtarget)[0];
        var endpo = getOptimalConnection(starttarget, endtarget)[1];
        var points = [];
        points = getKeyPoints(startpo,endpo);
        var connector = strokeConnector(points);
        connector.set({
            startPo:startpo.position,										//连接线起点坐标相对元素位置
            endPo:endpo.position,											//连接线终点坐标相对元素位置
            headId:starttarget.id,											//连接线起点连接元素id
            endId:endtarget.id												//连接线终点连接元素id
        });
        canvas.add(connector);												//绘制连接线
        connectors.push(connector);											//储存连接线
        canvas.sendToBack(connector);										//将连接线放在canvas堆栈最底层
        setConnectorsSelectable(false);
    }
    catch(e){
        alert(e);
    }
}























	